package com.dkd.manage.task.allocator.algorithm;

import com.dkd.manage.domain.Emp;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

@Slf4j
public class GeneticAlgorithm {
    private int populationSize;
    private int generations;
    private double crossoverRate;
    private double mutationRate;

    public GeneticAlgorithm(int popSize, int gens, double crossRate, double mutRate) {
        this.populationSize = popSize;
        this.generations = gens;
        this.crossoverRate = crossRate;
        this.mutationRate = mutRate;
    }

    public Map<Long, Double> optimize(List<Emp> candidates, Function<Emp, Double> fitnessFunction) {
        log.info("开始遗传算法优化，候选人数: {}", candidates.size());

        Map<Long, Double> results = new HashMap<>();

        // 初始化种群
        List<Emp> population = initializePopulation(candidates);

        // 进化过程
        for (int gen = 0; gen < generations; gen++) {
            // 评估适应度
            Map<Emp, Double> fitnessScores = evaluateFitness(population, fitnessFunction);

            // 选择
            List<Emp> selected = selection(population, fitnessScores);

            // 交叉
            List<Emp> offspring = crossover(selected);

            // 变异
            offspring = mutation(offspring);

            // 新一代种群
            population = offspring;

            log.debug("遗传算法第 {} 代完成", gen + 1);
        }

        // 最终评估
        for (Emp emp : population) {
            double fitness = fitnessFunction.apply(emp);
            // 添加遗传算法特有的优化过程
            double optimizedScore = fitness * (0.8 + 0.4 * Math.random());
            results.put(emp.getId(), optimizedScore);
        }

        log.info("遗传算法优化完成，生成 {} 个结果", results.size());
        return results;
    }

    private List<Emp> initializePopulation(List<Emp> candidates) {
        // 从候选人中随机选择形成初始种群
        return candidates.stream()
                .limit(populationSize)
                .collect(Collectors.toList());
    }

    private Map<Emp, Double> evaluateFitness(List<Emp> population, Function<Emp, Double> fitnessFunction) {
        Map<Emp, Double> fitnessScores = new HashMap<>();
        for (Emp emp : population) {
            fitnessScores.put(emp, fitnessFunction.apply(emp));
        }
        return fitnessScores;
    }

    private List<Emp> selection(List<Emp> population, Map<Emp, Double> fitnessScores) {
        // 轮盘赌选择
        double totalFitness = fitnessScores.values().stream().mapToDouble(Double::doubleValue).sum();

        return population.stream()
                .filter(emp -> {
                    double probability = fitnessScores.get(emp) / totalFitness;
                    return Math.random() < probability;
                })
                .collect(Collectors.toList());
    }

    private List<Emp> crossover(List<Emp> selected) {
        // 单点交叉
        List<Emp> offspring = new ArrayList<>();
        for (int i = 0; i < selected.size() - 1; i += 2) {
            if (Math.random() < crossoverRate) {
                // 模拟交叉操作
                offspring.add(selected.get(i));
                offspring.add(selected.get(i + 1));
            }
        }
        return offspring;
    }

    private List<Emp> mutation(List<Emp> offspring) {
        // 随机变异
        return offspring.stream()
                .map(emp -> {
                    if (Math.random() < mutationRate) {
                        // 模拟变异操作
                        return emp;
                    }
                    return emp;
                })
                .collect(Collectors.toList());
    }
}